home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / Resources / CutePDF 2.3 / converter.exe / GNUGS / GS_CIDCM.PS < prev    next >
Text File  |  2002-04-03  |  19KB  |  511 lines

  1. %    Copyright (C) 2000 artofcode LLC.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: gs_cidcm.ps,v 1.5.2.2 2002/04/02 13:55:47 mpsuzuki Exp $
  14. % Extending Font resource category with CIDFont-CMap fonts.
  15.  
  16. languagelevel 2 .setlanguagelevel currentglobal true setglobal
  17.  
  18.  
  19. % In the comments below, 'CSI' is an abbreviation/acronym for CIDSystemInfo.
  20. % We pre-scan resource files to retrieve the CSI from them.
  21. % First we define a hidden procset .prs_dict containing
  22. % necessary variables and procedures.
  23. % Then we redefine the old /Font category using this procset.
  24.  
  25. % We maintain internal caches for the CSI values retrieved from
  26. % resource files. This supposes that document doesn't uninstall
  27. % resource files. To disable caching, set enable_cache to false.
  28.  
  29. % We suppose that names starting with '.prs' do not appear in resource files.
  30. % If this causes any problem, this prefix should be systematically changed
  31. % in this file.  ('prs' is an abbreviation for 'prescan'.)
  32.  
  33. 25 dict begin
  34.  
  35. % Define local variables :
  36.  
  37. /.prs_dict currentdict def       % self-reference (constant)
  38. /.prs_empty 0 dict readonly def  
  39. /path_buffer 255 string def
  40. /name_buffer 255 string def
  41. /minus (-) 0 get def             % character code constant for '-'
  42. /period (.) 0 get def            % character code constant for '.'
  43. /CMap 10 dict def                % CSI cache for CMaps
  44. /CIDFont 10 dict def             % CSI cache for CIDFonts
  45. /enable_cache true def           % set false to disable cache
  46.  
  47. % The folloving variables are just placeholders for ones to be set
  48. % dynamically :
  49. /.prsFile 0 def                   % file to prescan
  50. /.prsResult 0 def                 % result of prescan
  51. /.prsDictCount 0 def              % save the dictionary stack depth
  52.  
  53. % Define a dummy CIDInit procset to use while pre-scanning :
  54.  
  55. /DummyCIDInit 15 dict 
  56. begin
  57.  
  58.   /begincmap {} def
  59.   /usecmap {pop} bind def
  60.  
  61.   {stop} bind
  62.   [ /begincodespacerange /endcodespacerange /beginnotdefchar /endnotdefchar
  63.     /beginnotdefrange /endnotdefrange /begincidchar /endcidchar /begincidrange 
  64.     /endcidrange /endcmap /usefont /StartData
  65.   ] {
  66.     1 index def
  67.   } bind forall
  68.   pop
  69.  
  70. currentdict end def
  71.  
  72. % Define a local 'findresource' for pre-scanning :
  73. % (it returns the dummy CIDInit instead of the regular CIDInit ProcSet)
  74.  
  75. /findresource { % <InstName> <CatName> findresource <inst>
  76.   2 copy /ProcSet eq exch             % /InstName /CatName bool /InstName
  77.   /CIDInit eq and {
  78.     pop pop //DummyCIDInit
  79.   } {
  80.     //findresource exec
  81.   } ifelse
  82. } bind def
  83.  
  84. % Define procedures for pre-scanning :
  85.  
  86. /StopIfCSIDefined {   % - StopIfCSIDefined -
  87.   
  88.   % Check if the dictionary stack contains a dictionary containing /CIDSystemInfo. 
  89.   % The search is limited to the top .prsDictCount dictionaries in the stack.
  90.   % If so, retrieve the CSI, and execute stop to terminate the pre-scanning of the file.
  91.   % Otherwise, do nothing, so the pre-scanning continues.
  92.  
  93.   countdictstack //.prs_dict /.prsDictCount get sub dup {
  94.     currentdict /CIDSystemInfo .knownget {
  95.       //.prs_dict exch /.prsResult exch put
  96.       stop
  97.     } if
  98.     currentdict exch end
  99.   } repeat {
  100.     begin
  101.   } repeat
  102. } bind def
  103.  
  104. /PrescanFile {     % - PrescanFile -
  105.   { //.prs_dict /.prsFile get token {      
  106.       dup type                          % token type
  107.       dup /nametype eq exch /operatortype eq or {
  108.         dup xcheck {
  109.           exec
  110.           //StopIfCSIDefined exec
  111.         } if
  112.       } if
  113.     } {
  114.       stop
  115.     } ifelse
  116.   } loop
  117. } bind odef
  118.  
  119. /GetCIDSystemInfoFromFile { % <file> GetCIDSystemInfoFromFile <CSI>
  120.   
  121.   % This procedure reads resource files with 'token',
  122.   % executing the tokens untill /CIDSystemInfo appears to be defined.
  123.   % Normally the resource file creates a new dictionary on
  124.   % dictionary stack and defines /CIDSystemInfo in it.
  125.   %
  126.   % Returns an empty dictionary if no CIDSystemInfo is found.
  127.  
  128.   //.prs_dict begin
  129.   /.prsFile exch def
  130.   /.prsResult //.prs_empty def
  131.   /.prsDictCount countdictstack def
  132.   { //PrescanFile } stopped pop
  133.   //.prs_dict /.prsResult get
  134.   end
  135. } bind def
  136.  
  137. /GetCIDSystemInfo {     % <InstName> <CatName> GetCIDSystemInfo <CSI>
  138.   
  139.   % Retrieve CSI, using caches.
  140.   
  141.   2 copy resourcestatus {
  142.     pop 2 lt {
  143.       findresource /CIDSystemInfo .knownget not {
  144.         //.prs_empty
  145.       } if
  146.     } {                                                      
  147.       dup //.prs_dict exch get                % /InstName /CatName CSIs
  148.       dup 3 index known
  149.       //enable_cache and {                            
  150.         exch pop exch get                     % CSI
  151.       } {                                                  
  152.         3 1 roll                              % CSIs /InstName /CatName
  153.         /Category findresource begin          % CSIs /InstName
  154.         dup //path_buffer ResourceFileName    % CSIs /InstName (path)
  155.         end                                   
  156.         currentglobal exch true setglobal     % CSIs /InstName g
  157.         mark exch                             % CSIs /InstName g [ (path)
  158.         { (r) file                            % CSIs /InstName g [ file
  159.           //GetCIDSystemInfoFromFile exec     % CSIs /InstName g [ CSI
  160.         } stopped {
  161.       % Cannot find file from Resource directory
  162.           cleartomark
  163.       % Try to find file from CIDFontmap
  164.       % Stack: CSIs /InstName g
  165.       1 index dup .CIDFontmapKnownget {
  166.           % Stack: CSIs /InstName g /InstName ValueInCIDFontmap
  167.           % We do look at CIDFontmap in global space.
  168.           % (When stopped, the space is set to local.)
  169.           true setglobal
  170.           1 index 3 1 roll
  171.           .CIDFontmapRunHandler
  172.           /CIDFont findresource /CIDSystemInfo get
  173.       } {
  174.           pop //.prs_empty             
  175.       } ifelse
  176.         } {
  177.           exch pop
  178.         } ifelse                              % CSIs /InstName g CSI
  179.         exch setglobal                        % CSIs /InstName CSI
  180.         dup 4 1 roll                          % CSI CSIs /InstName CSI
  181.         put                                   % CSI
  182.       } ifelse
  183.     } ifelse
  184.   } {
  185.     pop pop //.prs_empty
  186.   } ifelse
  187. } bind def
  188.  
  189. /IsCompatibleCSI {  % <CSI-M> <CSI-F> IsCompatibleCSI <bool>
  190.   
  191.   % The CSI in a CIDFont may be an array, a dict, or null.
  192.   % If it is an array, it must be of 1 element, which is a dict.
  193.   % In this case the dict is used for testing the compatibility.
  194.   % Two dicts are compatible iff they contain same /Ordering and /Registry.
  195.  
  196.   exch                                  % CSI-F CSI-M
  197.   { dup type /arraytype eq {
  198.       dup length 1 ne {
  199.         pop pop false exit
  200.       } if
  201.       0 get
  202.     } if                                % CSI-F CSI-M
  203.     dup type /dicttype ne {
  204.       pop pop false exit
  205.     } if                                % CSI-F <<CSI-M>>
  206.     exch                                % <<CSI-M>> CSI-F
  207.     dup type /dicttype ne {
  208.       pop pop false exit
  209.     } if                                % <<CSI-M>> <<CSI-F>>
  210.     true                                % <<CSI-M>> <<CSI-F>> bEQ
  211.     [/Registry /Ordering] {                    
  212.       2 index 1 index .knownget not {
  213.         1234567
  214.       } if                              % <<CSI-M>> <<CSI-F>> bEQ /key vF
  215.       exch                              % <<CSI-M>> <<CSI-F>> bEQ vF /key
  216.       4 index exch .knownget not {
  217.         7654321
  218.       } if                              % <<CSI-M>> <<CSI-F>> bEQ vF vM
  219.       eq and                            % <<CSI-M>> <<CSI-F>> bEQ
  220.     } forall
  221.     exch pop exch pop                   % bEQ
  222.     exit
  223.   } loop
  224. } bind def
  225.  
  226. /IsComposedOK {     % <CIDFontName> <CMapName> IsComposedOK <bool>
  227.   
  228.   % Check if the given CIDFont and CMap have compatible CSIs.
  229.  
  230.   exch                                  % /CMapName /CIDFontName
  231.   /CIDFont //GetCIDSystemInfo exec      % /CMapName CSI-F
  232.   dup type /dicttype eq {
  233.     dup length 0 ne {                          
  234.       exch                              % CSI-F /CMapName
  235.       /CMap //GetCIDSystemInfo exec     % CSI-F CSI-M
  236.       //IsCompatibleCSI exec            % bool
  237.     } {
  238.       pop pop false
  239.     } ifelse
  240.   } {
  241.     pop pop false
  242.   } ifelse
  243. } bind def
  244.  
  245. /IsComposedFont {   % <FontName> IsComposedFont <CIDFontName> <CMapName> true
  246.                     % <FontName> IsComposedFont false
  247.   
  248.   % Check if the given font name may be decomposed into CIDFont.CMap, CIDFont-CMap
  249.   % or into CIDFont--CMap, such that CIDFont and CMap have compatible CSIs.
  250.                                         % FontName
  251.   dup type /stringtype ne {
  252.     //name_buffer cvs
  253.   } if                                  % (FontName)
  254.   { dup length 2 sub -1 1 {
  255.                                         % (FontName) i
  256.       2 copy get dup //minus eq exch //period eq or {                
  257.         2 copy 2 copy                   % (FontName) i (FontName) i (FontName) i
  258.         2 copy get //minus eq {
  259.           2 copy 1 sub get //minus eq {
  260.             1 sub
  261.           } if
  262.         } if                            % (FontName) i (FontName) i (FontName) i0
  263.         0 exch getinterval cvn          % (FontName) i (FontName) i /CIDFontName
  264.         3 1 roll                        % (FontName) i /CIDFontName (FontName) i
  265.         1 add dup                       % (FontName) i /CIDFontName (FontName) i1 i1
  266.         5 index length                  % (FontName) i /CIDFontName (FontName) i1 i1 l
  267.         exch sub getinterval cvn        % (FontName) i /CIDFontName /CMapName
  268.         2 copy //IsComposedOK exec {    % (FontName) i /CIDFontName /CMapName 
  269.           4 2 roll pop pop              % /CIDFontName /CMapName
  270.           stop
  271.         } if
  272.         pop pop pop
  273.       } {
  274.         pop
  275.       } ifelse                          % (FontName)
  276.     } for
  277.     pop
  278.   } stopped
  279. } bind def
  280.  
  281. /ComposeName { % <CIDFont> <CMap> <scr> ComposeName <CIDFont-CMap>
  282.   dup dup 5 2 roll                        % (scr) (scr) /CIDFont /CMap (scr)
  283.   3 2 roll exch cvs length dup            % (scr) (scr) /CMap l0 l0
  284.   4 -1 roll exch //minus put              % (scr) /CMap l0
  285.   1 add dup                               % (scr) /CMap l1 l1
  286.   3 index dup length                      % (scr) /CMap l1 l1 (scr) L
  287.   2 index sub                             % (scr) /CMap l1 l1 (scr) LT
  288.   3 2 roll                                % (scr) /CMap l1 (scr) LT l1
  289.   exch getinterval                        % (scr) /CMap l1 (scrT)
  290.   3 2 roll exch cvs length                % (scr) l1 l2
  291.   add 0 exch getinterval                  % (CIDFont-CMap)
  292. } bind def
  293.  
  294.  
  295. % Define a few procedure templates to be modified dynamically :
  296.  
  297. currentpacking false setpacking
  298.  
  299. /BindAux {   % <proc> BindAux <proc>
  300.   0 exec
  301. } bind def
  302.  
  303. /EnumerateFontNames { %  - EnumerateFontNames ...
  304.   
  305.   % This is a pattern for enumeration procedure to be built dynamically,
  306.   % using Bind with a temporary dictionary.
  307.   % The following names will be replaced with specific objects
  308.   % during Bind : en_local_dict, scr, proc, Fonts, Category .
  309.  
  310.   end % Category
  311.   { 
  312.     0 1 2 {
  313.       en_local_dict exch /status exch put
  314.       Fonts {                                            
  315.         en_local_dict /status get eq {            
  316.           scr cvs                           % ... (Font)
  317.           proc exec                         %
  318.         } {
  319.           pop
  320.         } ifelse                            % ...
  321.       } forall
  322.     } for                                   % ...
  323.   } stopped
  324.   Category begin
  325.   { stop } if
  326. } bind def
  327.  
  328. setpacking
  329.  
  330. /Bind {    % <proc> Bind <proc>
  331.   
  332.   % Make a copy of the given procedure, binding in the values of all names
  333.   % defined in currentdict.
  334.   % Caution : this code cannot handle procedures that were already
  335.   % bound recursively.
  336.  
  337.   dup length array copy
  338.   dup length 1 sub -1 0 {                      
  339.     2 copy get                            % {precopy} i {elem}
  340.     dup dup type /arraytype eq exch xcheck and {
  341.                                           % {precopy} i {elem}
  342.       //BindAux exec                      % {precopy} i {elem_copy}
  343.       2 index 3 1 roll put                % {precopy}
  344.     } {
  345.       dup dup type /nametype eq exch xcheck and {
  346.                                           % {precopy} i {elem}
  347.         currentdict exch .knownget {            
  348.           2 index 3 1 roll put            % {precopy}
  349.         } {                                            
  350.           pop
  351.         } ifelse
  352.       } {
  353.         pop pop
  354.       } ifelse
  355.     } ifelse                              % {precopy}
  356.   } for                                   % {copy}
  357.   cvx
  358. } bind def
  359.  
  360. //BindAux 0 //Bind put   % bind the recursive call in 'Bind'.
  361.  
  362.  
  363.  
  364. % Redefine the /Font category with CIDFont-CMap construction :
  365.  
  366. % The following code supposes that the following names are not
  367. % defined in the old /Font category dictionary :
  368. % /IsComposedFont, /Bind, /IsComposedOK, /EnumerateFontNames .
  369.  
  370.  
  371. /Font /Category findresource dup length dict copy begin
  372.  
  373. /FindResource {  % <InstName> FindResource <inst>
  374.   dup //ResourceStatus exec {
  375.     pop pop //FindResource exec
  376.   } {                                                
  377.     dup //IsComposedFont exec {          % /FontName /CIDFontName /CMapName 
  378.       exch [ exch ] composefont          % inst
  379.     } {
  380.       //FindResource exec
  381.     } ifelse
  382.   } ifelse
  383. } bind def
  384.  
  385. /ResourceStatus {  % <InstName> ResourceStatus <nStatus> <nSize> true
  386.                    % <InstName> ResourceStatus false
  387.   dup //ResourceStatus exec {                    
  388.     3 2 roll pop true                     % nStatus nSize true
  389.   } {                                                  
  390.     //IsComposedFont exec {               % /CIDFontName /CMapName 
  391.       /CMap resourcestatus {              % /CIDFontName nStatusM nSizeM 
  392.         exch pop exch                     % nSizeM /CIDFontName 
  393.         /CIDFont resourcestatus {         % nSizeM nStatusF nSizeF 
  394.           exch pop                        % nSizeF nSizeM
  395.           dup 0 ge {
  396.             exch dup 0 ge {
  397.               add
  398.             } {
  399.               exch pop
  400.             } ifelse
  401.           } {
  402.             pop
  403.           } ifelse                        % nSize
  404.           2 exch true                     % nStatus nSize true
  405.         } {                        
  406.           pop pop pop false  % work around buggy resource file
  407.         } ifelse
  408.       } {                            
  409.         pop pop pop false    % work around buggy resource file
  410.       } ifelse
  411.     } {
  412.       false
  413.     } ifelse
  414.   } ifelse
  415. } bind def
  416.  
  417. /ResourceForAll { % <template> <proc> <scratch> ResourceForAll - 
  418.  
  419.   % We suppose that the resourceforall procedure does not 
  420.   % define or install new fonts, CMaps, and/or CIDFonts.
  421.  
  422.   % First we create 3 temporary dictionaries to store temporary data
  423.   % about fonts, CMaps and CIDFonts.
  424.   % These dictionaries must be created dynamically, to allow for a possible 
  425.   % recursive call to resourceforall from the resourceforall procedure.
  426.  
  427.   currentglobal false setglobal
  428.   20 dict 20 dict 20 dict
  429.   4 -1 roll setglobal                     % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  430.  
  431.   % Store resource names into local dictionaries :
  432.  
  433.   5 index [ 2 index {exch cvn dup put} aload pop ] cvx 5 index //ResourceForAll exec
  434.   (*)     [ 3 index {exch cvn dup put} aload pop ] cvx 5 index /CMap resourceforall
  435.   (*)     [ 4 index {exch cvn dup put} aload pop ] cvx 5 index /CIDFont resourceforall
  436.  
  437.   %% Make the list of fonts in the form (/Name status) :
  438.  
  439.                                           % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  440.   dup {                                              
  441.     //ResourceStatus exec {                        
  442.       pop 2 index                         % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> /Name nStatus <<Font>>
  443.       3 1 roll put                        % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  444.     } {
  445.       pop
  446.     } ifelse
  447.   } forall                                % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>>
  448.  
  449.   %% Add CIDFont-CMap to it (filtering duplicates) :
  450.  
  451.   3 2 roll  {                                        
  452.     3 index {                                        
  453.       3 1 roll                            % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /CIDFont /CMap
  454.       6 index //ComposeName exec          % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap (Font)
  455.       dup 8 index .stringmatch {              
  456.         cvn                               % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font
  457.         dup 4 index exch known {
  458.           pop pop
  459.         } {                                            
  460.           2 index                         % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font /CIDFont
  461.           4 2 roll                        % (templ) proc (scr) <<CMap>> <<Font>> /Font /CIDFont /CIDFont /CMap
  462.           //IsComposedOK exec {                
  463.             exch 2 index exch 2 put       % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont
  464.           } {
  465.             exch pop
  466.           } ifelse
  467.         } ifelse
  468.       } {
  469.         pop pop
  470.       } ifelse
  471.       dup                                 % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CIDFont
  472.     } forall
  473.     pop pop                               % (templ) proc (scr) <<CMap>> <<Font>>
  474.   } forall                                % (templ) proc (scr) <<CMap>> <<Font>>
  475.   exch pop                                % (templ) proc (scr) <<Font>>
  476.  
  477.   % Build the enumeration procedure :
  478.  
  479.   % Since the resourceforall procedure may leave values on the operand stack,
  480.   % we cannot simply store the enumerator's local data on the stack.
  481.   % We also cannot use a static dictionary to store local variables,
  482.   % because of possible recursion in the resourceforall procedure.
  483.   % To work around this, we create a copy of the enumeration procedure and
  484.   % bind it dynamically with a temporary dictionary, which contains
  485.   % local variables for the currently executing instance of resourceforall.
  486.  
  487.   currentdict
  488.   6 dict begin % the temporary dictionary
  489.     /Category exch def
  490.     /Fonts exch def
  491.     /scr exch def
  492.     /proc exch def
  493.     /en_local_dict currentdict def
  494.     //EnumerateFontNames //Bind exec      % (templ) Enumerator
  495.     /status 0 def % variable for the current status to enumerate - do not Bind with it !
  496.   end
  497.   exch pop                                % Enumerator
  498.  
  499.   % Do the enumeration :
  500.  
  501.   exec
  502. } bind def
  503.  
  504.  
  505. currentdict end /Font exch /Category defineresource pop
  506. end
  507. setglobal .setlanguagelevel
  508.